// ----------------------------------------
// Filename: main.c
// Description: Temperature Data Logger
// Author: Anton Jatmiko
// Date: 20 April 2014

// PIC18F44J10 Configuration Bit Settings

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

// CONFIG1L
#pragma config WDTEN = OFF      // Watchdog Timer Enable bit (WDT disabled (control is placed on SWDTEN bit))
#pragma config STVREN = OFF     // Stack Overflow/Underflow Reset Enable bit (Reset on stack overflow/underflow disabled)
#pragma config XINST = OFF      // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))

// CONFIG1H
#pragma config CP0 = OFF        // Code Protection bit (Program memory is not code-protected)

// CONFIG2L
#pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator)
#pragma config FOSC2 = ON       // Default/Reset System Clock Select bit (Clock selected by FOSC as system clock is enabled when OSCCON<1:0> = 00)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
#pragma config IESO = OFF       // Two-Speed Start-up (Internal/External Oscillator Switchover) Control bit (Two-Speed Start-up disabled)

// CONFIG2H
#pragma config WDTPS = 32768    // Watchdog Timer Postscale Select bits (1:32768)

// CONFIG3H
#pragma config CCP2MX = DEFAULT // CCP2 MUX bit (CCP2 is multiplexed with RC1)


#include "main.h"

static UINT16 CounterTimer2 = 0;
static UINT16 CounterDebounce = 0;
UINT16 CounterDebounceCycle = 0;
static UINT16 CounterUSB = 100;
static UINT16 CounterSample = 200;
static UINT16 CounterClickTime = 0;

TUINT16 CelcX10;

extern UINT8 Flash_RxData;
extern UINT8 Flash_CMD;
extern BOOL Flash_MFULL;
extern UINT8 CounterStage;
extern BOOL Flash_BusyRD;

static UINT8 DummyVar = 0;

BOOL SSPI_Flag = 0;

BOOL HMI_ButtonExecute = 0;
BOOL HMI_ButtonCurState = 0;
UINT8 HMI_ButtonWaitState = 0;
BOOL HMI_SamplingStart = 0;
BOOL USB_TxStart = 0;
BOOL HMI_ButtonHoldState = 0;
BOOL FirstClick = 0;
BOOL IgnoreDC = 0;

// ----------------------------------------
// myISR
//
// ISR to service all interrupts
// Input:
//   none
// Output:
//   none
// Conditions:
//   none
void interrupt myISR(void)
{
    // Timer 2 interrupt
    if (PIR1bits.TMR2IF)
    {
        ++CounterTimer2;

        if (HMI_ButtonWaitState == 0)      // Wait for press
        {
            HMI_ButtonCurState = !PORTDbits.RD7;

            if (!FirstClick)
            {
                if (HMI_ButtonCurState)
                {
                    HMI_ButtonWaitState = 1;
                    CounterDebounce = CounterTimer2 + 10;
                    IgnoreDC = 0;
                }
            }
            else
            {
                if (!USB_TxStart)
                {
                    ++CounterClickTime;

                    if (CounterClickTime > 400)
                    {
                        CounterClickTime = 0;
                        HMI_ButtonExecute = 1;
                        HMI_ButtonWaitState = 3;
                        IgnoreDC = 0;
                    }
                    else
                    {
                        if (HMI_ButtonCurState)     // Double Click
                        {
                            CounterClickTime = 0;
                            FirstClick = 0;
                            if (!HMI_SamplingStart)
                            {
                                IgnoreDC = 0;
                                Flash_CMD = 0xC7;   // Bulk erase
                                main_InitBulkErase();   // reset all
                            }
                            else
                            {
                                IgnoreDC = 1;
                                HMI_ButtonWaitState = 1;
                                CounterDebounce = CounterTimer2 + 10;
                            }
                        }
                    }
                }
            }
        }
        else if (HMI_ButtonWaitState == 1) // Debounce
        {
            if (CounterTimer2 == CounterDebounce)
            {
                HMI_ButtonCurState = !PORTDbits.RD7;

                if (HMI_ButtonCurState)
                {
                    if (!IgnoreDC)
                        FirstClick = 1;

                    HMI_ButtonWaitState = 2;
                }
                else
                {
                    HMI_ButtonWaitState = 0;
                }
            }
        }
        else if (HMI_ButtonWaitState == 2) // Wait for release
        {
            HMI_ButtonCurState = !PORTDbits.RD7;

            if (!HMI_ButtonCurState)
            {
                if (USB_TxStart)
                {
                    FirstClick = 0;
                }

                HMI_ButtonHoldState = 0;
                CounterDebounceCycle = 0;
                HMI_ButtonWaitState = 1;
                CounterDebounce = CounterTimer2 + 10; 
            }
            else        // HOLD BUTTON 2sec
            {
                if (!HMI_ButtonHoldState)
                    ++CounterDebounceCycle;
                else
                {
                    FirstClick = 0;
                    CounterDebounceCycle = 0;
                }

                if (CounterDebounceCycle == 2000)
                {
                    HMI_SamplingStart = 0;
                    LATBbits.LATB5 = 1;
                    USB_TxStart = !USB_TxStart;
                    Flash_BusyRD = USB_TxStart;
                    CounterUSB = CounterTimer2;
                    HMI_ButtonHoldState = 1;
                    CounterStage = 0;
                    FirstClick = 0;
                    CounterDebounceCycle = 0;

                    if (USB_TxStart)
                    {
                        Flash_CMD = 0x03;   // flash read
                        Flash_WriteCMD(Flash_CMD);
                    }   
                    else
                    {
                        Flash_CMD = 0;
                        Flash_Select(1);    // stop reading
                        Flash_ResetCBR();
                    }
                }
            }
            if (!Flash_BusyRD)
                    USB_TxStart = 0;
        }
        else if (HMI_ButtonWaitState == 3)
        {
            if (!Flash_MFULL)
            {
                if (HMI_ButtonExecute)
                {
                    HMI_SamplingStart = !HMI_SamplingStart;
                    LATBbits.LATB5 = !HMI_SamplingStart;
                    HMI_ButtonExecute = 0;
                }
                if (HMI_SamplingStart)
                {
                    Flash_CMD = 0x06;   // write enable
                    CounterSample = CounterTimer2;
                }
                else
                {
                    CounterStage = 0;
                    Flash_Select(1);    // release slave
                }
            }
        
            FirstClick = 0;
            HMI_ButtonWaitState = 0;
        }

        if (CounterTimer2 == CounterUSB)
        {
            if (SSPI_Flag)
            {
                UART_WriteChar(Flash_RxData);
                SSPI_Flag = 0;
                while (!SPI_Put(1));
            }
            
            CounterUSB = CounterTimer2 + 100;
        }

        if (HMI_SamplingStart)
        {
            if (CounterTimer2 == CounterSample)
            {
                if (!Flash_MFULL)
                {
                    Analog_StartSampling(1);
                }
                else
                    LATBbits.LATB5 = !LATBbits.LATB5;

                CounterSample = CounterTimer2 + 200;
            }
        }
        PIR1bits.TMR2IF = 0;
    }

    // UART Tx interrupt
    if (PIR1bits.TXIF)
    {
        PIR1bits.TXIF = 0;
    }

    // SPI interrupt
    if (PIR3bits.SSP2IF)
    {
        if (Flash_CMDHandle(Flash_CMD))
        {
            SSPI_Flag = 1;
        }
        PIR3bits.SSP2IF = 0;

        
    }

    // ADC interrupt
    if (PIR1bits.ADIF)
    {
        Analog_Temperature(&CelcX10);
        Flash_WriteCMD(Flash_CMD);

        PIR1bits.ADIF = 0;
    }

}

// ----------------------------------------
// main_InitBulkErase
//
// Reset all counters and disarm interrupts, preparing for bulk erase
// Input:
//   none
// Output:
//   none
// Conditions:
//   none
void main_InitBulkErase(void)
{
    CounterTimer2 = 0;
    CounterDebounce = 0;
    CounterDebounceCycle = 0;
    CounterUSB = 100;
    CounterSample = 200;
    CounterClickTime = 0;

    SSPI_Flag = 0;

    HMI_ButtonCurState = 0;
    HMI_ButtonWaitState = 0;
    HMI_SamplingStart = 0;
    USB_TxStart = 0;
    HMI_ButtonHoldState = 0;

    SPI_SetInterrupt(0);
    Analog_SetInterrupt(0);
    Timer_SetInterrupt(0);
}

/*
 *
 *
// ----------------------------------------
// main
//
// Execute all functions and commands
// Input:
//   none
// Output:
//   none
// Conditions:
//   none
 */
void main(void)
{   
    di();                       // Disable global interrupts

    // Initialise timer, ADC, HMI, flash and UART
    Timer_Init();
    Analog_Init();
    HMI_Init();
    Flash_Init();
    UART_Init();

    // Arm interrupts
    SPI_SetInterrupt(1);
    Analog_SetInterrupt(1);
    Timer_SetInterrupt(1);

    ei();                       // Enable global interrupts

    

    for(;;)
    {
        // Bulk Erase
        if (Flash_CMD == 0xC7)
        {
            di();

            Flash_BulkErase();          // Execute flash bulk erase
            LATBbits.LATB5 = 1;         // Reset LEDS

            // Arm interrupts
            SPI_SetInterrupt(1);
            Analog_SetInterrupt(1);
            Timer_SetInterrupt(1);

            ei();
        }
    }
    
}

